﻿using System;
using System.ComponentModel;
using System.Diagnostics.Contracts;
using System.Globalization;

namespace OpenWaves.Web.Controls
{
    /// <summary>
    /// Represents a position of a location on the Earth's surface using geographic latitude and longitude coordinate system.
    /// </summary>
    [Serializable]
    [TypeConverter(typeof(GeoPointConverter))]
    public class GeoPoint
    {
        /// <summary>
        /// Initializes a new instance of the GeoPoint class with specified latitude and longitude.
        /// </summary>
        /// <param name="latitude">Latitude component of the position in range [-90, 90].</param>
        /// <param name="longitude">Longitude component of the position in range [-180, 180].</param>
        public GeoPoint(double latitude, double longitude)
        {
            Contract.Requires(latitude >= -90 && latitude <= 90, "Precondition failed");
            Contract.Requires(longitude >= -180 && longitude <= 180, "Precondition failed");

            this.latitude = latitude;
            this.longitude = longitude;
        }

        private readonly double latitude;
        /// <summary>
        /// Gets the latitude component of this <see cref="GeoPoint"/>.
        /// </summary>
        public double Latitude
        {
            get { return this.latitude; }
        }

        private readonly double longitude;
        /// <summary>
        /// Gets the longitude component of this <see cref="GeoPoint"/>.
        /// </summary>
        public double Longitude
        {
            get { return this.longitude; }
        }

        /// <summary>
        /// Parses string representation of a <see cref="GeoPoint"/> into an instance of <see cref="GeoPoint" /> class.
        /// </summary>
        /// <param name="value">String representation of a <see cref="GeoPoint"/> formated as "latitude, longitude" where both components are floats (InvariantCulture).</param>
        /// <returns>New instance of <see cref="GeoPoint"/></returns>
        /// <exception cref="FormatException">value is a missformated string.</exception>
        public static GeoPoint Parse(string value)
        {
            Contract.Requires(value != null, "Precondition failed");

            string[] stringArray = value.Split(',');
            if(stringArray.Length != 2)
            {
                throw new FormatException("String should be in format \"lat,lng\"");
            }
            return new GeoPoint(double.Parse(stringArray[0], CultureInfo.InvariantCulture), double.Parse(stringArray[1], CultureInfo.InvariantCulture));
        }
    }
}